package job

import (
	"context"
	"encoding/json"
	"fmt"
	"go-api/internal/dao/model"
	"net/http"
	"time"

	"github.com/zeromicro/go-zero/core/logx"
	"gorm.io/gorm"

	"go-api/internal/dao/schema"
	"go-api/internal/svc"
)

type VideoResultCron struct {
	ctx    context.Context
	svcCtx *svc.ServiceContext
	db     *gorm.DB
	client *http.Client
}

func NewVideoResultCron(ctx context.Context, svcCtx *svc.ServiceContext) *VideoResultCron {
	return &VideoResultCron{
		ctx:    ctx,
		svcCtx: svcCtx,
		db:     svcCtx.DbSelect.GetDb(ctx, model.DB),
		client: getHTTPClient(),
	}
}

func (c *VideoResultCron) RunVideoResultJob() {
	for {
		// 从 Redis 队列中获取任务
		taskData, err := c.svcCtx.RedisClient.LPop(c.ctx, "video_result_queue").Result()
		if err != nil {
			//logx.Errorf("从 Redis 队列获取任务失败: %v", err)
			time.Sleep(1 * time.Second)
			continue
		}
		if taskData == "" {
			time.Sleep(1 * time.Second)
			continue
		}

		var info schema.CustomerOneTouchVideoTaskInfo
		err = json.Unmarshal([]byte(taskData), &info)
		if err != nil {
			logx.Errorf("解析任务数据失败: %v", err)
			continue
		}
		c.processResult(&info)
	}
}

func (c *VideoResultCron) processResult(info *schema.CustomerOneTouchVideoTaskInfo) {
	// 处理视频结果
	resp, err := c.client.Get(fmt.Sprintf(
		"http://video.yunshiyouke.com.cn/videoclips/Timeline/getResultByJobId?jobId=%s",
		info.JobId))
	if err != nil {
		logx.Errorf("查询视频结果失败: %v", err)
		return
	}
	defer resp.Body.Close()

	var result map[string]interface{}
	if err := json.NewDecoder(resp.Body).Decode(&result); err != nil {
		logx.Errorf("解析结果失败: %v", err)
		return
	}

	// 更新数据库
	c.updateVideoInfo(info, result)
}

func (c *VideoResultCron) updateVideoInfo(info *schema.CustomerOneTouchVideoTaskInfo, result map[string]interface{}) {
	// 使用事务更新
	tx := c.db.Begin()
	defer func() {
		if r := recover(); r != nil {
			tx.Rollback()
		}
	}()

	// 更新任务信息
	updateMap := map[string]interface{}{
		"video_url": result["mediaURL"],
		"cover_url": result["coverURL"],
		"status":    3, // 已完成状态
	}

	if err := tx.Model(&schema.CustomerOneTouchVideoTaskInfo{}).
		Where("id =?", info.ID).
		Updates(updateMap).Error; err != nil {
		tx.Rollback()
		logx.Errorf("更新视频信息失败: %v", err)
		return
	}

	// 更新主任务状态
	if err := tx.Model(&schema.CustomerOneTouchVideoTask{}).
		Where("id =?", info.CustomerOneTouchVideoTaskId).
		Update("status", 3).Error; err != nil {
		tx.Rollback()
		logx.Errorf("更新主任务状态失败: %v", err)
		return
	}

	tx.Commit()
}

// 公共方法
func (c *VideoResultCron) acquireLock(lockKey string) bool {
	return c.svcCtx.RedisClient.SetNX(c.ctx,
		fmt.Sprintf("cron_lock:%s", lockKey),
		1,
		4*time.Minute).Val()
}
